package com.example.train.common.config.security.service.impl;

import com.example.train.common.config.security.DynamicSecurityMetadataSource;
import com.example.train.common.config.security.service.DynamicSecurityService;
import com.example.train.model.SysPermission;
import com.example.train.service.SysPermissionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DynamicSecurityServiceImpl implements DynamicSecurityService {

    private Map<String, List<ConfigAttribute>> configAttributeMap = null;

    private final SysPermissionService sysPermissionService;

    public DynamicSecurityServiceImpl(SysPermissionService sysPermissionService) {
        this.sysPermissionService = sysPermissionService;
    }

    @PostConstruct
    public void init() {
        loadDataSource();
    }

    @Override
    public void loadDataSource() {
        log.info("Init load permission data source");
        Map<String, List<ConfigAttribute>> map = new ConcurrentHashMap<>();
        List<SysPermission> resourceList = sysPermissionService.selectAll(null);
        for (SysPermission permission : resourceList) {
            if (StringUtils.hasText(permission.getReqUrl()) && StringUtils.hasText(permission.getReqMethod())) {
                List<ConfigAttribute> configList = permission.getRoles().stream()
                        .map(r -> new SecurityConfig(r.getName())).collect(Collectors.toList());
                map.put(permission.getReqUrl() + DynamicSecurityMetadataSource.ACCESS_SEPARATOR + permission.getReqMethod(), configList);
            }
        }
        configAttributeMap = map;
    }

    @Override
    public Map<String, List<ConfigAttribute>> getConfigAttributeMap() {
        if (configAttributeMap.isEmpty()) {
            loadDataSource();
        }
        return configAttributeMap;
    }
}
